package com.wxmit.ot.gen.domain;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.wxmit.ot.gen.annotate.CodeTemplateParamAnn;
import com.wxmit.ot.gen.domain.dto.GenTableInitDto;
import com.wxmit.ot.gen.enums.Db2JavaFieldEnum;
import lombok.Data;
import lombok.experimental.Accessors;
import lombok.experimental.FieldNameConstants;

import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.*;

/**
 * 生成代码 表格信息
 *  此对象信息将映射为默认变量
 *
 * @author huangxiong
 * @version V1.0
 * @date 2023/2/22 17:04
 */
@Data
@Accessors(chain = true)
@FieldNameConstants
@TableName("ot_gen_table")
public class GenTable {

    @FieldNameConstants.Exclude
    @TableId(type = IdType.AUTO)
    private Long id;

    /**
     *  作者
     */
    @NotNull(message = "代码作者不能为空！")
    @CodeTemplateParamAnn("作者")
    private String author = "wxmit";

    /**
     *  包前缀
     */
    @NotNull(message = "包前缀不能为空！")
    @CodeTemplateParamAnn("包前缀")
    private String prePackage = "com.wxmit";

    @TableField(exist = false)
    @CodeTemplateParamAnn("基于包前缀生成的文件路径")
    private String preFile;

    /**
     *  表名
     */
    @NotNull(message = "表名不能为空！")
    @CodeTemplateParamAnn("表名")
    public String name;

    /**
     *  模块名
     */
    @NotNull(message = "模块名不能为空！")
    @CodeTemplateParamAnn("模块名")
    private String moduleName;

    /**
     *  业务名
     *  className 对应 demo
     *  ClassName 对应 Demo
     */
    @NotNull(message = "业务名不能为空！")
    @CodeTemplateParamAnn("业务名 ( 例：className 对应 demo ; ClassName 对应 Demo )")
    private String className;

    /**
     *  表注释
     */
    @CodeTemplateParamAnn("表注释")
    private String comment;


    @CodeTemplateParamAnn("数据库类型(全大写)")
    private String dbType = Db2JavaFieldEnum.DB_MYSQL;

    /** 创建时间 */
    @JsonFormat(pattern = "yyyy-MM-dd",timezone="GMT+8")
    @TableField(fill = FieldFill.INSERT)
    private Date createTime;

    /**
     *  扩展变量
     */
    @TableField(typeHandler = JacksonTypeHandler.class )
    @CodeTemplateParamAnn("扩展变量")
    private Map<String,String> extra;

    @NotNull(message = "模版组id 不能为空")
    private Long groupId;

    @TableField(exist = false)
    @NotEmpty(message = "表格列不能为空！")
    @Valid
    private List<GenTableColumn> columns;

    @TableField(exist = false)
    private GenTableColumn pkColumns;

    /**
     *  根据 initDto 构建 表格对象
     * @param initDto initDto
     * @return 表格对象
     */
    public static GenTable buildGenTableByInitDto(GenTableInitDto initDto){
        GenTable genTable = new GenTable();

        genTable.setName(initDto.getName());

        genTable.setClassName(tableName2className(genTable.getName()));
        genTable.setModuleName( genTable.getClassName());
        genTable.setComment(StrUtil.isEmpty(initDto.getComment()) ? initDto.getName() : initDto.getComment());
        genTable.setDbType(initDto.getDbType());

        List<GenTableColumn> columns = initDto.getColumns().stream().map(it->GenTableColumn.buildGenTableColumnByInitDto(it,initDto.getDbType())).toList();

        genTable.setColumns(columns);

        return genTable;
    }

    /**
     *   表格名 2 类名
     *   1. 全部转小写 （ T_USER 2 t_user ）
     *   2. 下划线转驼峰 （ t_user 2 tUser ）
     *   3. 首字母大写  ( tUser 2 TUser )
     * @param tableName 表格名
     * @return 类名
     */
    public static String tableName2className(String tableName){
        return StrUtil.upperFirst(StrUtil.toCamelCase(tableName.toLowerCase(Locale.ROOT)));
    }

    /**
     *  setId
     *   基于此处表格 与 表格列的父子关系，当 表格id被设置时，同时更新表格列的 tableId 字段
     * @param id id
     */
    public void setId(Long id){
        this.id = id;
        if(!CollectionUtil.isEmpty(this.getColumns())){
            this.getColumns().forEach(it->it.setTableId(id));
        }
    }

    public void setPrePackage(String prePackage){
        this.prePackage = prePackage;
        if(prePackage.isNull())return;
        setPreFile(prePackage.replace(".","/"));
    }

}
